home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / array.lha / array / COPYNOTE < prev    next >
Text File  |  1993-08-08  |  3KB  |  97 lines

  1. s noted in the README file, the current version of the array class
  2. oes not have a copy-constructor, although the first version had one.
  3. he first version was clearly wrong, and I thank Tom Cargill for
  4. ointing this out.
  5.  
  6.  have not been able to make the copy-constructor work properly with
  7. y compiler (AT&T 3.0.1), although I know what I would like to do.  If
  8. ou can find a useful work-around, or have a compiler that may handle
  9. he approach described below, please let me know.  As always, I will
  10. ppreciate your comments.
  11.  
  12. he code examples below are based on the declaration of Array<T>, see
  13. rray.H for details.
  14.  
  15.  
  16. orrect behaviour of copy-constructor.
  17.  
  18.  my view, the only correct behaviour for the array copy-constructor
  19. s to create copies of each element with the copy-constructor of the
  20. lement type.  In particular, I think the following implementation is
  21. rong:
  22.  
  23. emplate <class T>
  24. rray<T>::Array(const Array<T>& a)
  25.     : low(a.low), sz(a.sz)
  26.  
  27.   data = new T[sz];
  28.   assert(data != 0);
  29.   for (unsigned i = 0; i < sz; i++)
  30.     data[i] = a.data[i];
  31.  
  32.  
  33. t first creates an array, initializing every element with the default
  34. onstructor, and then uses the assignment operator to change the
  35. alues of the new array elements.  Of course, this approach works well
  36. or simple element types, such as, ints and doubles.
  37.  
  38.  
  39.  correct copy-constructor.
  40.  
  41. he original version had a copy-constructor that tried very hard to
  42. et the initialization right, and that part was in fact correct. The
  43. rick is to allocate the right amount of space without doing the
  44. efault initialization, and then do the element-wise initialization:
  45.  
  46. emplate <class T>
  47. rray<T>::Array(const Array<T>& a)
  48.     : low(a.low), sz(a.sz)
  49.  
  50.   data = (T*) new char[sizeof(T)*sz];
  51.   assert(data != 0);
  52.   for (unsigned i = 0; i < sz; i++)
  53.     new (data+i) T(a.data[i]);
  54.  
  55.  
  56. hat piece of code must then be matched by an appropriate destructor,
  57. hich calls the destructor for each element:
  58.  
  59. emplate <class T>
  60. rray<T>::~Array()
  61.  
  62.   for (unsigned i = 0; i < sz; i++)
  63.     data[i].T::~T();
  64.   delete (char *) data;
  65.  
  66.  
  67. nfortunately, Cfront 3.0.1 does not seem to recognize "T::~T" in a
  68. emplate, and now I have run out of ideas!  Maybe I just got it all
  69. rong, and in that case I would be terribly grateful for your advice.
  70.  
  71.  
  72. riginal error.
  73.  
  74. om Cargill found a related bug in my original code: that I mixed
  75. vector new" and "plain new" in my class.  The default constructor
  76. llocated a vector of Ts with
  77.  
  78.     new T[sz]
  79.  
  80. hile the copy-constructor allocated a raw piece of memory with
  81.  
  82.     (T*) new char[sizeof(T)*sz]
  83.  
  84. hich was then initialized.  However, the destructor assumed vector
  85. llocation:
  86.  
  87.     delete [] data;
  88.  
  89. hat happens is that you will run the destructors if the array was
  90. ade with the default constructor, but not if the array was made with
  91. he copy-constructor.  The behaviour depends on how Cfront implements
  92. ew of vectors. 
  93.  
  94. he solution is to only allocate raw storage (also in the default
  95. onstructor) and use explicit construction/destruction of the
  96. lements.
  97.